<template>
  <div class="auto-assign-panel">
    <div class="header">
      <div class="title">自动分配业务员</div>
      <div class="actions">
        <el-switch
          v-model="state.enabled"
          inline-prompt
          :disabled="limitRows.length === 0"
          active-text="运行中"
          inactive-text="未运行"
          @change="toggleRun"
        />

        <!-- 关闭 -->
        <el-button
          style="margin-left: 20px"
          type="info"
          text
          link
          size="mini"
          @click="appStore.toggleAutoVisible(false)"
          >隐藏</el-button
        >
      </div>
    </div>

    <div class="section">
      <div class="label">选择业务员</div>
      <el-select
        v-model="config.selectedIds"
        :disabled="state.enabled"
        multiple
        collapse-tags
        style="width: 100%"
      >
        <el-option v-for="u in userList" :key="u.value" :label="u.label" :value="u.value" />
      </el-select>
    </div>

    <!-- 配置模式：未运行时可编辑上限 -->
    <template v-if="!state.enabled">
      <div class="section" v-if="config.selectedIds.length">
        <div class="label">业务员分配上限</div>
        <el-table :data="limitRows" size="small" border>
          <el-table-column prop="name" label="业务员" width="150" />
          <el-table-column label="分配类型">
            <template #default="{ row }">
              <el-radio-group v-model="row.limitType" size="small">
                <el-radio-button label="设置单" :value="0" />
                <el-radio-button label="不限" :value="1" />
              </el-radio-group>
            </template>
          </el-table-column>
          <el-table-column label="上限">
            <template #default="{ row }">
              <span v-if="row.limitType === 1">不限</span>
              <el-input-number
                v-else
                v-model="row.limit"
                :min="1"
                size="small"
                style="width: 140px"
              />
            </template>
          </el-table-column>
        </el-table>
      </div>
    </template>

    <!-- 运行模式：只读显示状态 -->
    <template v-else>
      <div class="section">
        <div class="label">业务员分配上限：已选择 {{ config.selectedIds.length }} 个业务员</div>
      </div>
      <div class="section runSection">
        <div class="label">运行状态</div>
        <div class="status-box">
          <div
            v-for="row in limitRows"
            :key="row.id"
            @click="openHistory(row.id)"
            class="user-status"
          >
            <div class="name">
              {{ row.name }}
              <span
                v-if="row.limitType === 1 || (runtime.map[row.id] || 0) < row.limit"
                class="assigning"
              ></span>
              <span v-else class="limit-exceeded"></span>
            </div>
            <div class="count">分配：{{ runtime.map[row.id] || 0 }}</div>
          </div>
        </div>
      </div>
    </template>

    <!-- 分配历史弹窗 -->
    <el-dialog v-model="dialog.visible" width="680px">
      <template #header>{{ dialog.title }}</template>
      <el-table :data="dialog.data" border>
        <el-table-column prop="orderId" label="订单信息">
          <template #default="{ row }">
            <RowSlots slotName="orderSlot" :row="row" />
          </template>
        </el-table-column>
        <!-- 收货人信息 -->
        <el-table-column prop="logistics" label="收货人信息">
          <template #default="{ row }">
            <RowSlots slotName="logisticsSlot" :row="row" />
          </template>
        </el-table-column>
        <!-- 物流信息 -->
        <el-table-column prop="logisticsStatus" label="物流信息">
          <template #default="{ row }">
            <RowSlots slotName="logisticsStatusSlot" :row="row" />
          </template>
        </el-table-column>

        <!-- 下单/签收时间 -->
        <el-table-column prop="time" label="下单/签收时间">
          <template #default="{ row }">
            <RowSlots slotName="orderTimerSlot" :row="row" />
          </template>
        </el-table-column>
      </el-table>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { reactive, ref, computed, watch, onMounted, toRefs, PropType } from 'vue';
import { ElMessage } from 'element-plus';
import { listNotAssignedComplaintOrders } from '../../api/platformOrders/orders/list';
import { updateCustomerSalesman } from '../../api/customers';
import useAppStore from '@/store/modules/app';

const appStore = useAppStore();

const props = defineProps({
  users: {
    type: Array as PropType<User[]>,
    default: () => []
  }
});

const { users } = toRefs(props);

// ===== 类型定义 =====
interface User {
  userId: number;
  nickName: string;
}

interface OrderItem {
  customerId: number;
  orderId: string;
  time: string;
  // 可根据实际 API 补充字段
}

interface SalesmanRow {
  id: number;
  name: string;
  limitType: 0 | 1; // 0: 有限制, 1: 不限制
  limit: number | '-1';
}

interface RuntimeData {
  map: Record<number, number>; // 业务员ID -> 已分配数量
  history: Record<number, OrderItem[]>; // 业务员ID -> 分配记录
  nextIndex: number; // 轮询分配的起始索引（关键！）
}

interface ConfigData {
  selectedIds: number[];
  limits: Record<number, number | '-1'>;
}

interface StateData {
  enabled: boolean;
  timer: number | null;
}

const userList = computed(() =>
  (users.value || []).map((u: User) => ({
    value: u.userId,
    label: u.nickName
  }))
);

const config = reactive<ConfigData>({
  selectedIds: [],
  limits: {}
});

const state = reactive<StateData>({
  enabled: false,
  timer: null
});

const runtime = reactive<RuntimeData>({
  map: {},
  history: {},
  nextIndex: 0 // 初始从第一个业务员开始
});

const dialog = reactive({
  visible: false,
  title: '',
  data: [] as OrderItem[]
});

const limitRows = ref<SalesmanRow[]>([]);

// ===== 工具函数 =====
const getName = (id: number): string => {
  return userList.value.find((u) => u.value == id)?.label || '未知';
};

const getLimitConfig = (uid: number): { limitType: 0 | 1; limit: number | '-1' } => {
  const saved = config.limits[uid];
  if (saved === '-1') {
    return { limitType: 1, limit: '-1' };
  } else if (typeof saved === 'number') {
    return { limitType: 0, limit: saved };
  }
  return { limitType: 1, limit: '-1' };
};

// 检查是否有至少一个业务员可用（用于暂停判断）
const anyAvailable = (): boolean => {
  for (const row of limitRows.value) {
    const count = runtime.map[row.id] || 0;
    if (row.limitType === 1) return true;
    if (row.limitType === 0 && typeof row.limit === 'number' && count < row.limit) {
      return true;
    }
  }
  return false;
};

// ===== 监听 selectedIds 变化，重建 limitRows 并初始化 runtime =====
watch(
  [() => config.selectedIds, userList],
  () => {
    const newRows: SalesmanRow[] = [];
    config.selectedIds.forEach((uid) => {
      const { limitType, limit } = getLimitConfig(uid);
      const name = getName(uid);
      newRows.push({ id: uid, name, limitType, limit });

      // 初始化 runtime 状态
      if (runtime.map[uid] === undefined) runtime.map[uid] = 0;
      if (!runtime.history[uid]) runtime.history[uid] = [];
    });
    limitRows.value = newRows;

    // 修正 nextIndex 边界：防止数组长度变化后越界
    if (newRows.length === 0) {
      runtime.nextIndex = 0;
    } else if (runtime.nextIndex >= newRows.length) {
      runtime.nextIndex = 0;
    }

    saveAll();
  },
  { deep: true }
);

// 同步 limitRows 修改回 config.limits
watch(
  limitRows,
  (rows) => {
    const newLimits: Record<number, number | '-1'> = {};
    rows.forEach((row) => {
      newLimits[row.id] = row.limitType === 1 ? '-1' : row.limit;
    });
    config.limits = newLimits;
  },
  { deep: true }
);

// ===== 核心：轮询分配逻辑 =====
/**
 * 使用轮询（Round-Robin）策略分配一个订单
 * 从 runtime.nextIndex 开始，循环查找第一个可用业务员
 * @returns 是否成功分配
 */
const assignOrderByRoundRobin = async (order: OrderItem): Promise<boolean> => {
  const rows = limitRows.value;
  if (rows.length === 0) return false;
  let tried = 0;
  let currentIndex = runtime.nextIndex;

  // 最多尝试一轮（所有业务员）
  while (tried < rows.length) {
    const row = rows[currentIndex];
    const { id: uid, limitType, limit } = row;
    const currentCount = runtime.map[uid] || 0;

    // 判断是否可分配
    const canAssign =
      limitType === 1 || (limitType === 0 && typeof limit === 'number' && currentCount < limit);

    if (canAssign) {
      try {
        await updateCustomerSalesman({
          customerId: order.customerId,
          salesmanId: uid
        });

        // 分配成功：更新本地状态
        runtime.map[uid] = currentCount + 1;
        runtime.history[uid].push({
          ...order
        });

        // 更新 nextIndex：下次从下一个位置开始（循环）
        runtime.nextIndex = (currentIndex + 1) % rows.length;
        return true;
      } catch (err) {
        // API 失败视为“临时不可用”，继续尝试下一个
        console.warn(`分配失败（跳过该业务员）:`, { uid, customerId: order.customerId }, err);
      }
    }

    // 移动到下一个（循环）
    currentIndex = (currentIndex + 1) % rows.length;
    tried++;
  }

  // 一圈都没找到可用业务员
  return false;
};

// ===== 主循环 =====
const runLoop = async () => {
  try {
    const res = await listNotAssignedComplaintOrders();
    const orders = res?.rows || [];
    if (!orders.length) return;
    ElMessage.info(`监听到有订单: ${orders.length}条，正在分配`);
    if (limitRows.value.length === 0) return;

    let anyAssigned = false;

    // 逐个分配订单（使用轮询策略）
    for (const order of orders) {
      const success = await assignOrderByRoundRobin(order);
      if (success) {
        anyAssigned = true;
      }
    }

    // 如果本轮无任何分配成功，且确实全满，则自动暂停
    if (!anyAssigned && !anyAvailable()) {
      state.enabled = false;
      ElMessage.warning('全部业务员达到上限，已自动暂停');
    }
  } catch (err) {
    console.error('自动分配异常:', err);
  } finally {
    saveAll();
  }
};

// ===== 定时器控制 =====
const startTimer = () => {
  stopTimer();
  (window as any).stopTimer = stopTimer;
  // 每分钟执行一次
  state.timer = window.setInterval(runLoop, 60000);
};

const stopTimer = () => {
  if (state.timer !== null) {
    console.log('暂停');
    clearInterval(state.timer);
    state.timer = null;
  }
};

const toggleRun = () => {
  appStore.toggleAutoRunning(state.enabled);
  if (state.enabled) {
    startTimer();
  } else {
    stopTimer();
  }
  saveAll();
};

// ===== 对话框 =====
const openHistory = (uid: number) => {
  dialog.title = getName(uid) + ' 的分配记录';
  dialog.data = [...(runtime.history[uid] || [])];
  dialog.visible = true;
};

// ===== 持久化 =====
const STORAGE_KEY = 'auto_assign_panel_v2'; // 版本升级，避免旧数据冲突

const saveAll = () => {
  const data = {
    config: { ...config },
    runtime: { ...runtime },
    state: { enabled: state.enabled }
  };
  try {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
  } catch (e) {
    console.warn('保存配置失败:', e);
  }
};

// 将对象的 string key 转为 number key（修复 JSON 序列化问题）
const restoreNumberKeys = <T,>(obj: Record<string, T>): Record<number, T> => {
  const result: Record<number, T> = {};
  for (const key in obj) {
    result[Number(key)] = obj[key];
  }
  return result;
};

onMounted(() => {
  const raw = localStorage.getItem(STORAGE_KEY);
  // 当刷新页面的时候
  (window as any).autoAssignSalesInitialized = true;
  if (!raw) return;

  try {
    const { config: c, runtime: r, state: s } = JSON.parse(raw);

    // 恢复 config
    config.selectedIds = (c?.selectedIds || []).map(String);
    if (c?.limits) {
      config.limits = restoreNumberKeys(c.limits);
      for (const uid in config.limits) {
        const val = config.limits[uid];
        if (val !== '-1') {
          config.limits[uid] = val;
        }
      }
    }

    // 恢复 runtime（注意：nextIndex 是 number，无需转换）
    if (r?.map) runtime.map = restoreNumberKeys(r.map);
    if (r?.history) runtime.history = restoreNumberKeys(r.history);
    if (typeof r?.nextIndex === 'number') runtime.nextIndex = r.nextIndex;

    // 恢复 state
    if (s?.enabled !== undefined) {
      state.enabled = s.enabled;
      appStore.toggleAutoRunning(state.enabled);
    }

    // 注意：limitRows 尚未生成，nextIndex 边界将在 watch 中修正
    if (state.enabled) startTimer();
  } catch (e) {
    console.error('恢复配置失败:', e);
  }
});
</script>

<style lang="scss" scoped>
.auto-assign-panel {
  padding: 16px;
  width: 705px;
  border-radius: 16px;
  display: flex;
  flex-direction: column;
  gap: 15px;

  .header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    .title {
      font-size: 18px;
      color: #535353;
    }
  }

  .section {
    .label {
      font-weight: 600;
      margin-bottom: 6px;
    }

    .status-box {
      display: flex;
      gap: 10px;
      flex-wrap: wrap;
      .user-status {
        padding: 12px;
        border-radius: 12px;
        background: #eff5ff;
        min-width: 160px;
        cursor: pointer;

        .name {
          font-weight: 600;
          margin-bottom: 6px;
          display: flex;
          justify-content: space-between;
          align-items: center;

          span {
            width: 10px;
            height: 10px;
            border-radius: 50%;
            display: inline-block;
          }

          .assigning {
            background: #409eff;
          }

          .limit-exceeded {
            background: #f56c6c;
          }
        }

        .count {
          font-size: 14px;
          color: #666;
        }
      }
    }
  }

  .runSection {
    max-height: calc(100vh - 220px);
    overflow-y: auto;
  }
}
</style>
